package com.hymall.aspect;

import com.hymall.anno.AddLog;
import com.hymall.bean.MarketAdmin;
import com.hymall.bean.MarketLog;
import com.hymall.bean.MarketOrder;
import com.hymall.bean.common.BaseRespVo;
import com.hymall.mapper.MarketOrderMapper;
import com.hymall.service.admin.MarketLogService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.Map;

/**
 * TODO 在订单上增加的注解
 * <p>
 * 先让方法执行，根据返回的BaseRespVo判断进行的操作
 *
 * @author: 叶熠彬
 * @description: 在Controller层增加日志信息的Aspect
 * @date: 2022/7/17 14:42
 */

@Aspect
@Component
public class LogAspect {

    @Autowired
    MarketLogService logService;
    @Autowired
    HttpServletRequest request;
    @Autowired
    MarketOrderMapper orderMapper;

    //切入点采用anno方式
    @Pointcut("@annotation(com.hymall.anno.AddLog)")
    public void logPointcut() {
    }


    @Around("logPointcut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        //不知为啥
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        BaseRespVo proceed = (BaseRespVo) joinPoint.proceed();

        //判断方法是否有注解
        if (method.isAnnotationPresent(AddLog.class)) {
            Subject subject = SecurityUtils.getSubject();
            PrincipalCollection principals = subject.getPrincipals();
            MarketLog newLog = getLog();
            if (principals == null) {
                newLog.setAdmin(proceed.getErrmsg());
                newLog.setType(1);
                newLog.setStatus(true);
                newLog.setAction("退出");
                if ("0:0:0:0:0:0:0:1".equals(request.getRemoteAddr())) {
                    newLog.setIp("127.0.0.1");
                }
                logService.addLog(newLog);
                return proceed;
            }

            MarketAdmin primaryPrincipal = (MarketAdmin) principals.getPrimaryPrincipal();
            AddLog addLog = method.getAnnotation(AddLog.class);
            //拿到方法运行结果
            //日志的一些值用方法生成
            if (primaryPrincipal == null) {
                newLog.setAdmin("匿名用户");
            } else {
                //操作人
                newLog.setAdmin(primaryPrincipal.getUsername());
            }
            //按注解的type写入类型
            newLog.setType(addLog.type());
            //按注解的action写入操作
            newLog.setAction(addLog.action());

            //分发
            if (newLog.getType() == 1) {
                String action = newLog.getAction();
                //登录相关操作
                if ("登录".equals(action)) {
                    if (proceed.getErrno() == 0) {
                        newLog.setStatus(true);
                    } else {
                        newLog.setStatus(false);
                        //返回页面错误信息
                        newLog.setResult(proceed.getErrmsg());
                    }
                }
                //管理员相关操作
                if (action.contains("管理员")) {
                    setLogAdminMsg(newLog, proceed);
                }
                if ("0:0:0:0:0:0:0:1".equals(request.getRemoteAddr())) {
                    newLog.setIp("127.0.0.1");
                }
                //写入数据库
                logService.addLog(newLog);
            }
            //TODO 订单相关操作
            if (newLog.getType() == 2) {
                String action = newLog.getAction();
                Object[] args = joinPoint.getArgs();
                Map map = (Map) args[0];
                Integer orderId = (Integer) map.get("orderId");
                MarketOrder marketOrder = orderMapper.selectByPrimaryKey(orderId);
                String result = "订单编号" + " " + marketOrder.getOrderSn();
                if (proceed.getErrno() == 0) {
                    newLog.setStatus(true);
                    newLog.setResult(result);
                } else {
                    newLog.setStatus(false);
                    newLog.setResult(proceed.getErrmsg());
                }
                logService.addLog(newLog);
            }
        }
        return proceed;
    }


    /**
     * 设置操作管理员账号的日志信息的状态和result
     *
     * @author: 叶熠彬
     * @date: 2022/7/17 17:04
     * @param: [log, proceed]
     * @return: void
     */
    private void setLogAdminMsg(MarketLog log, BaseRespVo proceed) {
        if (proceed.getErrno() == 0) {
            log.setStatus(true);
            MarketAdmin admin = (MarketAdmin) proceed.getData();
            log.setResult(admin.getUsername());
        } else {
            log.setStatus(false);
            log.setResult(proceed.getErrmsg());
        }
    }


    /**
     * 新建一个带时间、deleted默认值、和ip的MarketLog
     *
     * @author: 叶熠彬
     * @date: 2022/7/17 16:29
     * @param: []
     * @return: com.hymall.bean.MarketLog
     */
    private MarketLog getLog() {
        MarketLog marketLog = new MarketLog();
        marketLog.setDeleted(false);
        marketLog.setAddTime(new Date());
        marketLog.setUpdateTime(new Date());
        marketLog.setIp(request.getRemoteAddr());
        return marketLog;
    }
}
